#include "pch.hpp"
#include "Compiler.hpp"

#include <engine.entity/System.hpp>

using namespace Engine::Edit;




Compiler::Compiler(services::provider::ptr provider)
	: m_scheduler(provider->service<services::scheduler>())
	, m_scriptSystem(Engine::Script::System::create(boost::bind(&Compiler::callback, this, _1)))
	, m_compiling(false)
{
	// TODO: Register types with the engine....
	Entity::System::registerType(m_scriptSystem);
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Compiler::~Compiler()
{
	while(m_compiling);
}
///////////////////////////////////////////////////////////////////////////////////////////////////




boost::optional<Compiler::Compilation> Compiler::compile(const Scripts& scripts)
{
	if(m_compiling)
		return boost::optional<Compilation>();

	bool okay = false;
	m_compiling = true;
	BOOST_SCOPE_EXIT((&okay)(&m_compiling))
	{
		if(!okay)
			m_compiling = false;
	}
	BOOST_SCOPE_EXIT_END;



	return m_scheduler->execute<CompilationResult>([&,scripts](services::progress_listener) mutable -> CompilationResult
	{
		BOOST_SCOPE_EXIT((&m_compiling))
		{
			m_compiling = false;
		}
		BOOST_SCOPE_EXIT_END;

		auto builder = m_scriptSystem->builder();

		m_messages.clear();
		builder.start("unnamed");

		foreach(const auto& pair, scripts)
		{
			builder.add(pair.first, pair.second);
		}

		auto module = builder.build();
		return CompilationResult(module, m_messages);
	});

	okay = true;
}
///////////////////////////////////////////////////////////////////////////////////////////////////

Compiler::Types Compiler::types()
{
	return m_scriptSystem->types();
}
///////////////////////////////////////////////////////////////////////////////////////////////////

void Compiler::callback(logger::entry entry)
{
	m_messages.push_back(entry);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
